package com.google.code.chaotic.client;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import com.google.code.chaotic.dto.CommuterDto;
import com.google.code.chaotic.dto.CommutingHabitDto;
import com.google.code.chaotic.dto.LatLonDto;

public class ClientTestUtil {

	public static ArrayList<LatLonDto> generateOrigins(int maxCount,
			boolean visual) {
		String imageFilename = "/home/hadi/projects/chaos" + "/frontTier/test"
				+ "/images/distro_residential_zones.png";

		// Residential Zones Scanner
		ZoneScanner.Data data = new ZoneScanner.Data();
		double myHue = Math.toRadians(42) / (2 * Math.PI);
		double range = Math.toRadians(3) / (2 * Math.PI);
		data.hueRanges = new double[][] { { myHue, range } };
		data.paintColor = Color.GREEN;
		data.markerColor = Color.MAGENTA;
		data.centerX = 370; // Lon: 101.710402
		data.centerY = 360; // Lat: 3.15746
		data.maxRadius = 500;
		data.centerLon = 101.710402;
		data.centerLat = 3.15746;
		data.xScale = 0.094913 / 340;// 0.094913 Lon : 340 px
		data.yScale = 0.10716 / 383;// 0.10716 Lat : 383 px

		return generationLatLons(imageFilename, maxCount, data, visual);
	}

	public static ArrayList<LatLonDto> generateDestinations(int maxCount,
			boolean visual) {
		String imageFilename = "/home/hadi/projects/chaos" + "/frontTier/test"
				+ "/images/distro_commercial_mixuse_zones.png";

		// Commercial Zones Scanner
		ZoneScanner.Data data = new ZoneScanner.Data();
		double hue1 = Math.toRadians(228) / (2 * Math.PI);
		double range1 = Math.toRadians(6) / (2 * Math.PI);
		double hue2 = Math.toRadians(181) / (2 * Math.PI);
		double range2 = Math.toRadians(2) / (2 * Math.PI);
		data.hueRanges = new double[][] { { hue1, range1 }, { hue2, range2 } };
		data.paintColor = Color.ORANGE;
		data.centerX = 364; // Lon: 101.710402
		data.centerY = 350; // Lat: 3.15746
		data.maxRadius = 500;
		data.centerLon = 101.710402;
		data.centerLat = 3.15746;
		data.xScale = 0.094913 / 320;// 0.094913 Lon : 318 px
		data.yScale = 0.10716 / 355;// 0.10716 Lat : 355 px
		data.markerColor = Color.BLUE;

		return generationLatLons(imageFilename, maxCount, data, visual);
	}

	public static ArrayList<LatLonDto> generationLatLons(String imageFilename,
			int maxCount, ZoneScanner.Data data, boolean visual) {

		ImageIcon icon = new ImageIcon(imageFilename);
		JLabel label = new JLabel(icon);

		int width = icon.getIconWidth();
		int height = icon.getIconHeight();
		BufferedImage buffImage = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		buffImage.getGraphics().drawImage(icon.getImage(), 0, 0, //
				width - 1, height - 1, 0, 0, width - 1, height - 1, label);

		if (visual) {
			JFrame frame = new JFrame();
			label.setIcon(new ImageIcon(buffImage));
			label.setHorizontalTextPosition(JLabel.CENTER);
			label.setVerticalTextPosition(JLabel.BOTTOM);
			frame.setContentPane(label);
			frame.pack();
			if (frame.getWidth() < 1)
				frame.setSize(400, 600);
			frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
			frame.setVisible(true);

			data.label = label;
		}
		data.image = buffImage;
		data.maxCount = maxCount;

		ZoneScanner scanner = new ZoneScanner(data);
		Thread rendererThread = new Thread(scanner);
		rendererThread.start();

		try {
			rendererThread.join();

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return scanner.getLatLons();
	}

	//
	//
	//

	public static final class ZoneScanner implements Runnable {

		public static class Data {
			public BufferedImage image;
			public JLabel label;
			public int maxCount;
			public double[][] hueRanges;
			public Color paintColor;
			public Color markerColor;
			public int centerX;
			public int centerY;
			public double centerLon;
			public double centerLat;
			public double xScale;
			public double yScale;
			public int maxRadius;
		}

		private final Data data = new Data();
		private ArrayList<LatLonDto> latLons;

		public ZoneScanner(Data data) {
			this.data.image = data.image;
			this.data.label = data.label;
			this.data.maxCount = data.maxCount;
			this.data.hueRanges = data.hueRanges;
			this.data.paintColor = data.paintColor;
			this.data.markerColor = data.markerColor;
			this.data.centerX = data.centerX;
			this.data.centerY = data.centerY;
			this.data.maxRadius = data.maxRadius;
			this.data.centerLon = data.centerLon;
			this.data.centerLat = data.centerLat;
			this.data.xScale = data.xScale;
			this.data.yScale = data.yScale;
		}

		@Override
		public synchronized void run() {

			Graphics2D g2D = data.image.createGraphics();
			float[] hsbVals = new float[3];
			ArrayList<Point> scannedPoints = new ArrayList<Point>(100000);

			g2D.setColor(data.paintColor);

			Rectangle bounds = data.image.getRaster().getBounds();

			int radius = 0;
			// while (radius < 500) {
			// radius += 10;
			// graphics.drawOval(centerX - radius, centerY - radius, //
			// 2 * radius, 2 * radius);
			// label.repaint();
			// // try {
			// // Thread.sleep(100);
			// //
			// // } catch (InterruptedException e) {
			// // // TODO Auto-generated catch block
			// // e.printStackTrace();
			// // }
			// }
			radius = 0;
			double radian = 0;
			while (radius < data.maxRadius) {
				double TwoPI = 2 * Math.PI;
				if (radian < TwoPI) {
					radian += 0.1 / (radius == 0 ? 1 : radius);
					// radian += 0.015;
				} else {
					radian = 0;
					radius += 1;
					try {
						if (data.label != null)
							Thread.sleep(5);

					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				// try {
				int x = (int) (data.centerX + Math.cos(radian) * radius);
				int y = (int) (data.centerY + Math.sin(radian) * radius);
				Point point = new Point(x, y);
				if (!bounds.contains(point))
					continue;
				int rgb = data.image.getRGB(x, y);
				Color color = new Color(rgb);
				int red = color.getRed();
				int green = color.getGreen();
				int blue = color.getBlue();
				Color.RGBtoHSB(red, green, blue, hsbVals);
				float hue = hsbVals[0];
				for (double[] hueRange : data.hueRanges)
					if (Math.abs(hue - hueRange[0]) < hueRange[1]) {
						g2D.drawRect(x, y, 0, 0);
						scannedPoints.add(point);
						if (data.label != null)
							data.label.repaint();
						break;
					}
				// } catch (ArrayIndexOutOfBoundsException e) {
				// }
			}
			int pointsCount = scannedPoints.size();
			System.out.println("Scanned points count: " + pointsCount);
			ArrayList<LatLonDto> dtos = new ArrayList<LatLonDto>(Math.min(
					data.maxCount, pointsCount));

			g2D.setColor(data.markerColor);
			for (double d = 0; d < pointsCount; //
			d += (double) pointsCount / data.maxCount) {

				Point point = scannedPoints.get((int) d);
				// g2D.fillOval(point.x - 3, point.y - 3, 7, 7);
				g2D.fillOval(point.x - 2, point.y - 2, 5, 5);
				if (data.label != null)
					data.label.repaint();
				LatLonDto dto = new LatLonDto();
				dto.setLongitude(data.centerLon + (point.x - data.centerX)
						* data.xScale);
				dto.setLatitude(data.centerLat - (point.y - data.centerY)
						* data.yScale);
				dtos.add(dto);
				try {
					if (data.label != null)
						// Thread.sleep(10);
						Thread.sleep(1);

				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			latLons = dtos;
		}

		public synchronized ArrayList<LatLonDto> getLatLons() {
			return latLons;
		}
	}

}